#ifndef __BASE_MUTEX_H_
#define __BASE_MUTEX_H_

#include <pthread.h>
#include <assert.h>
#include <iostream>

namespace BASE{
	class Mutex{
		public:
			Mutex(){
				pthread_mutex_init(&mutex, NULL);
			}
			virtual ~Mutex(){
				int ret = pthread_mutex_destroy(&mutex);
				assert(ret == 0);
			}
			void writelock(){
				pthread_mutex_lock(&mutex);
			}

			void unlock(){
				pthread_mutex_unlock(&mutex);
			}
			pthread_mutex_t * getMutex(){
				return &mutex;
			}

		private:
			Mutex(const Mutex& mutex);
			Mutex& operator=(const Mutex & mutex);
		private:
			pthread_mutex_t mutex;
	};

	class RWMutex{
		public:
			RWMutex(){
				pthread_rwlock_init(&mutex, NULL);	
			}
			void readlock(){
				pthread_rwlock_rdlock(&mutex);
			}

			void writelock(){
				pthread_rwlock_wrlock(&mutex);
			}

			void unlock(){
				pthread_rwlock_unlock(&mutex);
			}

			virtual ~RWMutex(){
				int ret = pthread_rwlock_destroy(&mutex);
				assert(ret == 0);
			}
		private:
			RWMutex(const RWMutex & mutex);
			RWMutex & operator= (const RWMutex & mutex);
		private:
			pthread_rwlock_t mutex;
	};

	template<typename MTX, bool>
	class BaseLock{
		public:
			BaseLock(MTX& _mtx):mtx(_mtx){
				mtx.writelock();
			}
			virtual ~BaseLock(){
				mtx.unlock();
			}
		private:
			MTX & mtx;

	};
	
	template<>
	inline BaseLock<RWMutex, false>::BaseLock(RWMutex & _mtx):mtx(_mtx){
		mtx.readlock();
	}

	typedef BaseLock<RWMutex, true> WLock;
	typedef BaseLock<RWMutex, false> RLock;
	typedef BaseLock<Mutex, true> Lock;
}
#endif
